package com.stockz.equity.scanner.view;

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Vector;

import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;

import org.metawidget.swing.SwingMetawidget;
import org.metawidget.swing.widgetprocessor.binding.beanutils.BeanUtilsBindingProcessor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.Ordered;

import com.stockz.equity.charting.display.screen.AbstractDisplayableScreenConfiguration;
import com.stockz.equity.charting.util.ContextUtil;
import com.stockz.equity.charting.view.widget.JLabelTextSetter;
import com.stockz.equity.charting.view.widget.JProgressBarUpdator;
import com.stockz.equity.charting.view.widget.ScripNameComboBox;
import com.stockz.equity.model.Scrip;
import com.stockz.equity.pattern.View;
import com.stockz.equity.scanner.Scanner;
import com.stockz.equity.scanner.callback.OnScannerEventCallback;
import com.stockz.equity.scanner.model.ScannerEvent;
import com.stockz.equity.scanner.model.ScannerEvent.EventType;

//@Component
public class ScannerView extends JPanel implements View, Ordered {
	private static final long serialVersionUID = -1440424809016183236L;
	
	@Autowired
	Scanner scanner;
	@Autowired
	ScripNameComboBox scripNameComboBox;
	private JTable scanResultsTable;
	
	private final BeanUtilsBindingProcessor beanUtilsBindingProcessor = new BeanUtilsBindingProcessor();
	private final SwingMetawidget swingMetaWidget = new SwingMetawidget();
	
	private class ScripMatch implements Comparable<ScripMatch>{
		private Scrip scrip;
		private Double matchStrength = new Double(0);
		
		public Scrip getScrip() {
			return scrip;
		}
		public void setScrip(Scrip scrip) {
			this.scrip = scrip;
		}
		public double getMatchStrength() {
			return matchStrength;
		}
		public void setMatchStrength(double matchStrength) {
			this.matchStrength = matchStrength;
		}
		@Override
		public int compareTo(ScripMatch o) {
			return matchStrength.compareTo(o.matchStrength);
		}
	}
	
	public ScannerView(){
		setName("Scanner");
		setLayout(new BorderLayout(0, 0));
		
		final JPanel resultsPanel = new JPanel();
		final JPanel configurationPanel = null;
		swingMetaWidget.addWidgetProcessor(beanUtilsBindingProcessor);	
		resultsPanel.setLayout(new BorderLayout(0, 0));
		
		scanResultsTable = new JTable();
		scanResultsTable.setRowSelectionAllowed(true);
		scanResultsTable.setFillsViewportHeight(true);
		scanResultsTable.setAutoCreateRowSorter(true);
		scanResultsTable.setAutoCreateColumnsFromModel(true);
		
		final DefaultTableModel tableModel = new DefaultTableModel(null,new String[]{"Select","Scrip","Strength"}){
			private static final long serialVersionUID = 8337213154754973637L;
		
			private Class[] columnClassArray = new Class[]{Boolean.class,Scrip.class,Double.class};
			
			@Override
			public Class getColumnClass(int columnIndex) {
				return columnClassArray[columnIndex];
			}
		};
		scanResultsTable.setModel(tableModel);
		
		
		JPanel actionPanel = new JPanel();
		resultsPanel.add(actionPanel, BorderLayout.NORTH);
		actionPanel.setLayout(new BorderLayout(0, 0));
		
		JPanel selectionActionPanel = new JPanel();
		actionPanel.add(selectionActionPanel, BorderLayout.EAST);
		
		JLabel lblSelect = new JLabel("Select");
		selectionActionPanel.add(lblSelect);
		
		JButton btnAll = new JButton("All");
		selectionActionPanel.add(btnAll);
		btnAll.addActionListener(new ActionListener(){
			@Override
			public void actionPerformed(ActionEvent e) {
				for(int i = 0; i < scanResultsTable.getRowCount(); i++){
					tableModel.setValueAt(Boolean.TRUE, i, 0);
				}
			}
		});
		
		JButton btnNone = new JButton("None");
		selectionActionPanel.add(btnNone);
		btnNone.addActionListener(new ActionListener(){
			@Override
			public void actionPerformed(ActionEvent e) {
				for(int i = 0; i < scanResultsTable.getRowCount(); i++){
					tableModel.setValueAt(Boolean.FALSE, i, 0);
				}
			}
		});
		
		JPanel westPanel = new JPanel();
		actionPanel.add(westPanel, BorderLayout.WEST);
		
		JButton btnCharts = new JButton("Charts");
		westPanel.add(btnCharts);
		btnCharts.addActionListener(new ActionListener(){

			@Override
			public void actionPerformed(ActionEvent e) {
				scripNameComboBox.setModel(new DefaultComboBoxModel(getSelectedScrips()));
				//MainFrame.getTabbedPane().setSelectedIndex(1);
			}
			
		});
		
		
		JButton btnAddToWatchlist = new JButton("Add to Watchlist");
		westPanel.add(btnAddToWatchlist);

		
		JScrollPane scrollPane = new JScrollPane(scanResultsTable);
		resultsPanel.add(scrollPane, BorderLayout.CENTER);
		
		JPanel statusPanel = new JPanel();
		resultsPanel.add(statusPanel, BorderLayout.SOUTH);
		statusPanel.setLayout(new BorderLayout(0, 0));
		
		final JProgressBar scanProgressBar = new JProgressBar();
		scanProgressBar.setStringPainted(true);
		statusPanel.add(scanProgressBar, BorderLayout.SOUTH);
		
		JPanel messagePanel = new JPanel();
		statusPanel.add(messagePanel, BorderLayout.NORTH);
		messagePanel.setLayout(new BoxLayout(messagePanel, BoxLayout.X_AXIS));
		
		final JLabel lblTotal = new JLabel("Total : ");
		messagePanel.add(lblTotal);
		
		java.awt.Component horizontalGlue = Box.createHorizontalGlue();
		messagePanel.add(horizontalGlue);
		
		final JLabel lblScanned = new JLabel("Scanned : ");
		messagePanel.add(lblScanned);
		
		java.awt.Component horizontalGlue_1 = Box.createHorizontalGlue();
		messagePanel.add(horizontalGlue_1);
		
		final JLabel lblSkipped = new JLabel("Skipped : ");
		messagePanel.add(lblSkipped);
		
		java.awt.Component horizontalGlue_2 = Box.createHorizontalGlue();
		messagePanel.add(horizontalGlue_2);
		
		final JLabel lblMatched = new JLabel("Matched :");
		messagePanel.add(lblMatched);
		
		JPanel controlPanel = new JPanel();
		add(controlPanel, BorderLayout.NORTH);
		controlPanel.setLayout(new BorderLayout(0, 0));
		
		JPanel screenPanel = new JPanel();
		controlPanel.add(screenPanel, BorderLayout.NORTH);
		
		final JComboBox screenComboBox = new JComboBox();
		screenComboBox.setModel(
				new DefaultComboBoxModel(
						new Vector<AbstractDisplayableScreenConfiguration>(
								ContextUtil.getApplicationContext().getBeansOfType(AbstractDisplayableScreenConfiguration.class).values())));
		screenPanel.add(screenComboBox);
		screenComboBox.setSelectedIndex(0);
		
		screenComboBox.addItemListener(new ItemListener(){
			@Override
			public void itemStateChanged(ItemEvent e) {
				if(e.getStateChange() == ItemEvent.SELECTED){
					AbstractDisplayableScreenConfiguration config = 
						(AbstractDisplayableScreenConfiguration)screenComboBox.getSelectedItem();
					remove(swingMetaWidget);
					swingMetaWidget.removeAll();
					swingMetaWidget.setToInspect(config.getConfiguration());
					add(swingMetaWidget);
				}
			}
		});
		
		final JButton btnScan = new JButton("Scan");
		screenPanel.add(btnScan);
		final JButton btnCancel = new JButton("Cancel");
		btnCancel.setEnabled(false);
		screenPanel.add(btnCancel);
		btnCancel.addActionListener(new ActionListener(){
			@Override
			public void actionPerformed(ActionEvent e) {
				scanner.cancel();
			}
		});
		btnScan.addActionListener(new ActionListener(){
			
			@Override
			public void actionPerformed(ActionEvent e) {
				swingMetaWidget.getWidgetProcessor(BeanUtilsBindingProcessor.class).save(swingMetaWidget);
				remove(swingMetaWidget);
				swingMetaWidget.removeAll();
				Runnable runnable = new Runnable(){
					
					public void run(){
						tableModel.getDataVector().clear();
						tableModel.fireTableDataChanged();
						OnScannerEventCallback callback = new OnScannerEventCallback(){
							@Override
							public void onScannerEvent(final ScannerEvent event) {
								
								if(EventType.OnScanStart.equals(event.getEventType())){
									add(resultsPanel, BorderLayout.CENTER);
									btnScan.setEnabled(false);
									btnCancel.setEnabled(true);
									scanProgressBar.setMaximum(event.getTotalScripCount());
									scanProgressBar.setMinimum(0);
									scanProgressBar.setValue(0);
									JLabelTextSetter.setText(lblTotal, "Total : "+event.getTotalScripCount());
								}else if(EventType.OnMatch.equals(event.getEventType())){
									JLabelTextSetter.setText(lblMatched, "Matched : "+event.getTotalMatchCount());
									tableModel.addRow(new Object[]{Boolean.FALSE,event.getScrip(),event.getMatchStrength()});
								}else if(EventType.OnScripScanEnd.equals(event.getEventType())){
									JLabelTextSetter.setText(lblScanned, "Scanned : "+event.getCurrentScripIndex());
									JProgressBarUpdator.update(scanProgressBar, event.getCurrentScripIndex());
								}else if(EventType.OnScripScanSkipped.equals(event.getEventType())){
									JLabelTextSetter.setText(lblSkipped, "Skipped : "+event.getTotalSkippedCount());
								}else if(EventType.OnScanEnd.equals(event.getEventType())){
									btnScan.setEnabled(true);
									btnCancel.setEnabled(false);
								}
							}
						};
						
						List<OnScannerEventCallback> callbackList = new ArrayList<OnScannerEventCallback>(1);
						callbackList.add(callback);
						
						AbstractDisplayableScreenConfiguration screen = (AbstractDisplayableScreenConfiguration)screenComboBox.getSelectedItem();
						if(screen == null){
							screen = (AbstractDisplayableScreenConfiguration)screenComboBox.getItemAt(0);
						}
						scanner.scan(screen.getScreen(),callbackList);
					}
				};
				Thread thread = new Thread(runnable);
				thread.start();
			}
		});
	}
	
	@Override
	public int getOrder() {
		return 2;
	}

	public Vector<Scrip> getSelectedScrips(){
		Vector<Scrip> list = new Vector<Scrip>();
		List<ScripMatch> scripMatchList = new ArrayList<ScripMatch>();
		for(int i = 0; i < scanResultsTable.getRowCount(); i++){
			if((Boolean)scanResultsTable.getValueAt(i, 0)){
				ScripMatch scripMatch = new ScripMatch();
				scripMatch.setScrip((Scrip)scanResultsTable.getValueAt(i, 1));
				scripMatch.setMatchStrength((Double)scanResultsTable.getValueAt(i, 2));
				scripMatchList.add(scripMatch);
			}
		}
		
		Collections.sort(scripMatchList);
		
		for(ScripMatch scripMatch : scripMatchList){
			list.add(scripMatch.getScrip());
		}
		
		return list;
	}
}
